import 'dart:convert';
import 'dart:io';

import 'package:bruno/bruno.dart';
import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';

import 'package:get/get.dart' as gx;
import 'responseinterceptor.dart';
import 'resultdata.dart';
import 'topdiointerceptor.dart';
import 'urlpath.dart';
import 'package:path_provider/path_provider.dart';

class HttpManager {
  static HttpManager _instance = HttpManager._internal();
  late Dio _dio;

  static const CODE_SUCCESS = 200;
  static const CODE_TIME_OUT = -1;
  static const CONNECT_TIMEOUT = 60000;

  factory HttpManager() => _instance;

  ///通用全局单例，第一次使用时初始化
  HttpManager._internal() {
    _dio = Dio(BaseOptions(
      baseUrl: UrlPath.baseUrl,
      connectTimeout: CONNECT_TIMEOUT,
    ));
    _dio.interceptors.add(TopDioIntercepter());
    _dio.interceptors.add(ResponseInterceptors());
  }

  static HttpManager getInstance({String? baseUrl}) {
    if (baseUrl == null) {
      return _instance._normal();
    } else {
      return _instance._baseUrl(baseUrl);
    }
  }

  //用于指定特定域名
  HttpManager _baseUrl(String baseUrl) {
    if (_dio != null) {
      _dio.options.baseUrl = baseUrl;
    }
    return this;
  }

  //一般请求，默认域名
  HttpManager _normal() {
    if (_dio != null) {
      if (_dio.options.baseUrl != UrlPath.baseUrl) {
        _dio.options.baseUrl = UrlPath.baseUrl;
      }
    }
    return this;
  }

  ///通用的GET请求
  get(api, {params, withLoading = true}) async {
    gx.Get.log('--get--' + UrlPath.baseUrl + api);
    gx.Get.log('--get--' + jsonEncode(params));

    if (withLoading) {
      EasyLoading.show();
    }

    Response response;

    try {
      response = await _dio.get(api, queryParameters: params);
      if (response.data != null) {
        return response.data;
      }
    } on DioError catch (e) {
      gx.Get.log('--get--' + _dio.options.baseUrl);
      gx.Get.log(api);
      gx.Get.log(jsonEncode(params));
      gx.Get.log('-DioError-' + e.message);

      if (e.type == DioErrorType.connectTimeout) {
        BrnToast.show('链接超时', gx.Get.context!);
      } else if (e.type == DioErrorType.sendTimeout) {
        BrnToast.show('请求超时', gx.Get.context!);
      } else if (e.type == DioErrorType.cancel) {
        BrnToast.show('取消请求', gx.Get.context!);
      } else {
        var _msg = '网络错误';
        var _data = e.response?.data;
        if (_data is Map) {
          _msg = _data['msg'] ?? '网络错误';
        }
        _saveValue(DateTime.now().toIso8601String() +
            ':' +
            UrlPath.baseUrl +
            api +
            '--' +
            jsonEncode(params).toString() +
            '---error:' +
            e.toString() +
            '---errortype:' +
            e.type.toString());
        BrnToast.show(_msg, gx.Get.context!);
      }
    }
    return errorResult;
  }

  ///通用的POST请求
  post(api, {params, withLoading = true, showErrorInfo = true}) async {
    gx.Get.log(UrlPath.baseUrl + api);
    gx.Get.log('--params---post' + jsonEncode(params).toString());

    if (withLoading) {
      EasyLoading.show();
    }

    Response response;
    // print('-params-'+params..toString());
    try {
      response = await _dio.post(api, data: params);
      if (response.data != null) {
        return response.data;
      }
    } on DioError catch (e) {
      gx.Get.log(_dio.options.baseUrl);
      gx.Get.log(api);
      gx.Get.log(params.toString());
      gx.Get.log('-DioError-' + e.message);
      if (showErrorInfo) {
        if (e.type == DioErrorType.connectTimeout) {
          BrnToast.show('链接超时', gx.Get.context!);
        } else if (e.type == DioErrorType.sendTimeout) {
          BrnToast.show('请求超时', gx.Get.context!);
        } else if (e.type == DioErrorType.cancel) {
          BrnToast.show('取消请求', gx.Get.context!);
        } else {
          var _msg = '网络错误';
          var _data = e.response?.data;
          if (_data is Map) {
            _msg = _data['msg'] ?? '网络错误';
          }

          _saveValue(DateTime.now().toIso8601String() +
              ':' +
              UrlPath.baseUrl +
              api +
              '--' +
              jsonEncode(params).toString() +
              '---error:' +
              e.toString() +
              '---errortype:' +
              e.type.toString());

          BrnToast.show(_msg, gx.Get.context!);
        }
      }
    }
    return errorResult;
  }

  //上传文件

  uploadFiles(api,
      {required List<MultipartFile> multipartFiles,
      withLoading = true,
      CancelToken? cancelToken}) async {
    FormData formData = FormData.fromMap({'files': multipartFiles});

    Response response =
    await HttpManager()._dio.post(api, data: formData,onSendProgress:  (int sent, int total) {
      EasyLoading.showProgress(sent/total,status: '上传中...');
    });

    EasyLoading.dismiss();


    return response.data;
  }

  //单个上传大文件  用于上传视频
  uploadBigFile(api, String path, String name,
      Function(int sent, int total) listener) async {
    // FormData formData = FormData.fromMap({'files': multipartFiles});

    Response response = await HttpManager()._dio.post(api,
        data: FormData.fromMap(
            {'file': await MultipartFile.fromFile(path, filename: name)}),
        onSendProgress: (int sent, int total) {
      listener(sent, total);
    });
    return response.data;
  }

  final errorResult = ErrorResultData({'code': -999, 'data': []}, false, -1);

  ///下载文件到本地
  ///urlPath 文件Url
  ///savePath 本地保存位置
  ///downloadProgressCallBack 下载文件回调
  static Future<Response> downloadFile(String urlPath, String savePath,
      {DownloadProgressCallBack? downloadProgressCallBack}) async {
    Dio dio = Dio();
    return await dio.download(urlPath, savePath,
        onReceiveProgress: downloadProgressCallBack);
  }
 

  /**

   * 此方法返回本地文件地址

   */

  Future<File> _getLocalFile() async {
    // 获取文档目录的路径

    Directory appDocDir = await getApplicationDocumentsDirectory();

    String dir = appDocDir.path;

    final file = new File('$dir/httplog.txt');

    // print(file);

    return file;
  }

  /**

   * 保存value到本地文件里面

   */

  void _saveValue(String value) async {
    try {
      File f = await _getLocalFile();

      IOSink slink = f.openWrite(mode: FileMode.append);

      slink.write('$value\n');

      // await fs.writeAsString('$value');

      value = '';

      slink.close();
    } catch (e) {
      // 写入错误

      print('写入错误:' + e.toString());
    }
  }
}

ResultData resultError(DioError e) {
  Response errorResponse;
  if (e.response != null) {
    errorResponse = e.response!;
  } else {
    errorResponse =
        Response(statusCode: 666, requestOptions: RequestOptions(path: ''));
  }
  if (e.type == DioErrorType.connectTimeout ||
      e.type == DioErrorType.receiveTimeout) {
    errorResponse.statusCode = HttpManager.CODE_TIME_OUT;
  }
  return ResultData(
      errorResponse.statusMessage, false, errorResponse.statusCode!);
}
/// count 当前下载进度
/// total 下载总长度
typedef DownloadProgressCallBack = Function(int count, int total);